package com.core.framework.db.jdbc;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;

import com.core.framework.db.IDao;
import com.core.framework.db.jdbc.annotation.DTO;
import com.core.framework.db.jdbc.annotation.DtoUtils;
import com.core.framework.db.jdbc.page.Page;
import com.core.framework.db.jdbc.support.JdbcTemplateHelp;
import com.core.framework.db.jdbc.support.dialect.AbstractDialect;
import com.core.framework.db.jdbc.support.dialect.SqlDialectFactory;
import com.core.framework.tools.reflect.BeanReflectUtil;
import com.core.log.Log;
import com.util.AppUtils;
/**
 * 基础DAO 用来处理业务中出现的数据库操作
 * @author 刘涛  刘利
 * @since Jun 21, 2012
 * @param <T> 实体对象
 * @param <PK> 主键ID
 */
public class BaseDao<T, PK extends Serializable> extends JdbcDao implements
		IDao<T, PK> {

	protected Class<T> entityClass = null;
	static private AbstractDialect dialect  = SqlDialectFactory.createSQLdialect();
	String pkey = "";
	String tableName;

	public BaseDao() {
		try {
			this.entityClass = BeanReflectUtil
					.getSuperClassGenricType(getClass());
			if (DtoUtils.getDtoInfo(entityClass) != null) {
				DtoUtils dto = DtoUtils.getDtoInfo(entityClass);
				tableName = dto.tableName();
				pkey = dto.pkey();
			} else {
				tableName = getTableName(entityClass);
			}
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}
	
	public String getTableName() {
		return tableName;
	}
	
	private String getTableName(Class<T> entityClass) {
		return entityClass.getSimpleName();
	}

	public void excute(String sql, Object... objects) {
			Log.debug("SQL:["+sql+" ] 参数：["+objects+"]");
			this.getJdbcTemplate().update(sql, objects);
	}

	public void excute(String[] sqls) {
			Log.debug("SQL:"+sqls);
			this.getJdbcTemplate().batchUpdate(sqls);
	}

	public Integer getInt(String sql, Object... objects) {
		Log.debug("[SQL:"+sql+" 参数："+objects+"]");
		return this.getJdbcTemplate().queryForInt(sql, objects);
	}

	public List<T> getList(String sql, Object... objects) {
		Log.debug("SQL:["+sql+" ] 参数：["+objects+"]");
		return getList(sql,entityClass,objects);
	}
	
	public List<T> getList(String sql, Class<T>clazz,Object... objects) {
		Log.debug("SQL:["+sql+" ] 参数：["+objects+"]");
		List<T> ifs = (List<T>)this.getJdbcTemplate().query(sql, getRowMapper(clazz),objects);
		this.getJdbcTemplate().queryForList(sql, objects);
		return ifs;
	}



	public List<?> getListBySql(String sql, Class<?> cla, Object... objects) {
		Log.debug("SQL:["+sql+" ] 参数：["+objects+"]");
		if(cla.isAnnotationPresent(DTO.class))
			return getJdbcTemplate().query(sql, getRowMapper(cla),objects);
		else
			//throw new Exception("ddd");
			return null;
			
	}

	public T getObject(String sql, Object... objects) {
		Log.debug("SQL:["+sql+" ] 参数：["+objects+"]");
		T obj = this.getJdbcTemplate().queryForObject(sql, getRowMapper(entityClass), objects);
		return obj;
	}

	public T getObject(PK key) {
		
		String sql = "select * from "+this.tableName+" where "+this.pkey +"= ?";
		Log.debug("SQL:["+sql+" ] 参数PK ：["+key+"]");
		T obj = this.getJdbcTemplate().queryForObject(sql, getRowMapper(entityClass),new Object[]{key});
		return obj;
	}

	public Object getObjectBySql(String sql, Class<?> cla, Object... objects) {
		Log.debug("SQL:["+sql+" ] 参数：["+objects+"]");
		Object obj = null;
		if(cla.isAnnotationPresent(DTO.class)){
			List<?> ifs = this.getJdbcTemplate().query(sql, getRowMapper(cla),objects);
			if(ifs.size()>=0)
				obj = ifs.get(0);
		}
		return obj;
	}
	
	public void saveAll(List<T> list) {
		if(null != list &&list.size()>0){
			for(T obj : list)
				this.saveObject(obj);
		}
	}

	public T saveObject(T obj) {
		if (obj == null)
            return null;
		if(obj.getClass().isAnnotationPresent(DTO.class)){
        Class<?> clazz = obj.getClass();
        DtoUtils dto = DtoUtils.getDtoInfo(clazz);
        if (dto != null) {
            Log.debug("返回的类内容:["+obj+"]");
            insert(dto.tableName(), obj);
            return obj;
        }else
        	return null;
		}else{
			Log.error("实体类没有标记为DTO !");
			return null;
		}
	}
	public T saveObjectByAutoUUID(T obj) {
		if (obj == null)
            return null;
		if(obj.getClass().isAnnotationPresent(DTO.class)){
        Class<?> clazz = obj.getClass();
        DtoUtils dto = DtoUtils.getDtoInfo(clazz);
        if (dto != null) {
            String uuid = java.util.UUID.randomUUID().toString();
            BeanReflectUtil.setFieldValue(obj, dto.pkey(), uuid);
            Log.debug("返回的类内容:["+obj+"]");
            insert(dto.tableName(), obj);
            return obj;
        }else
        	return null;
		}else{
			Log.error("实体类没有标记为DTO !");
			return null;
		}
	}

	
	private void insert(String tableName, Object obj) {
		Map<String, Object> map = BeanReflectUtil.bean2Map(obj);
		StringBuilder sb = new StringBuilder(100);
		StringBuilder sbparam = new StringBuilder(30);
		Object[] keys = map.keySet().toArray();
		for(Object key :keys){
			sb.append(key).append(",");
			sbparam.append("? ,");
		}
		sb = sb.delete(sb.length()-1, sb.length());
		sbparam = sbparam.delete(sbparam.length()-1, sbparam.length());
		String sql = "insert into "+tableName+" ( "+sb.toString()+" ) values ( "+sbparam.toString()+" )";
		Log.debug("插入数据的SQL:["+sql+"]----参数结合：["+Arrays.asList(map.values().toArray())+"]");
		this.getJdbcTemplate().update(sql, map.values().toArray());
	}
	public static void main(String[] args){
//		Info info = new Info();
//		info.setAge(12L);
//		info.setName("曹操");
//		info.setId(12213213123L);
//		insertNObj("userinfo",info);
	}

	public void updateAll(List<T> list) {

		if(null != list &&list.size()>0){
			for(T obj : list)
				updateObject(obj);
		}
	}

	public T updateObject(T obj) {
		if (obj == null)
            return null;
        Class<?> clazz = obj.getClass();
        DtoUtils dto = DtoUtils.getDtoInfo(clazz);
        if (dto != null) {
        	Map<String, Object> map = BeanReflectUtil.bean2Map(obj);
        	StringBuilder setsql = new StringBuilder(100);
        	
        	Object[] keys = map.keySet().toArray();
    		for(Object key :keys){
    			setsql.append(key).append("=?,");
    		}
    		setsql = setsql.delete(setsql.length()-1, setsql.length());
    		
            String sql = "update "+dto.tableName()+" set "+setsql.toString()+" where "+dto.pkey()+" = ?";
            Log.debug("修改数据的SQL:["+sql+"]");
           Object[] param = new Object[map.values().size()+1];
           System.arraycopy(map.values().toArray(), 0, param, 0, param.length-1);
           param[map.values().size()] = map.get(dto.pkey());

            this.getJdbcTemplate().update(sql, param);
            return obj;
        }else
        	return null;
	}

	public T updateObject(String sql, Object... objects) {
		int n = this.getJdbcTemplate().update(sql, objects);
        Log.debug("修改数据的SQL:["+sql+"]----参数:["+objects+"]");
		if(n>0){
			return newObj();
		}else
			return null;
	}
	
	public T newObj() {
		T t = AppUtils.getBean(entityClass);
		return t;
	}
	

	public String getKeyName() {
		return pkey;
	}
	public List<T> getList(PK pk) {
		String sql = "select * from "+this.getTableName()+" where "+this.pkey+"= ? " ;
		return this.getJdbcTemplate().queryForList(sql, this.entityClass,pk);
	}

	public void deleteObject(PK pk) 
	{
			String sql = "delete from "+this.getTableName()+"  where "+this.pkey +"= ? " ;
			this.getJdbcTemplate().update(sql,pk);
	}
	
//========================辅助函数================================================
	
	
	@SuppressWarnings({ "unchecked", "hiding" })
	private <T> RowMapper<T> getRowMapper(Class<T> clazz) { 
        if (String.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.stringPRM;
        else if (Long.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.longPRM;
        else if (Date.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.datePRM;
        else if (Object.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.objPRM;
        else if (Integer.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.intPRM;
        else if (Double.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.doublePRM;
        else if (Map.class.equals(clazz))
            return (RowMapper<T>) JdbcTemplateHelp.mapPRM;
        else
            return BeanPropertyRowMapper.newInstance(clazz);
    }

	@SuppressWarnings("unchecked")
	public PK getPkValue(T obj) {
		if (obj == null)
			return null;
		Object r = BeanReflectUtil.getFieldValue(obj, getKeyName());
		if (r == null || r.equals(0) || r.equals(0L) || r.equals(""))
			return null;
		return (PK) r;
	}
	public Page<T> findPage(Page<T> page) {
		String countSQL = dialect.getPageCountSQL(tableName, null);
		int ICount = this.queryForInt(countSQL);
		page.setTotalCount(ICount);
		String pageSQL = dialect.getPageSQL(page, tableName, null);
		List<T> pageList = this.getList(pageSQL, this.entityClass);
		page.setResult(pageList);
		return page;
	}
	public Page<T> findPage(Page<T> page, String whereContent) 
	{
		String countSQL = dialect.getPageCountSQL(tableName, whereContent);
		int ICount = this.queryForInt(countSQL);
		page.setTotalCount(ICount);
		String pageSQL = dialect.getPageSQL(page, tableName, whereContent);
		List<T> pageList = this.getList(pageSQL, this.entityClass);
		page.setResult(pageList);
		return page;
	}
}
